
package com.lerning.edu.commons.http;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.google.common.base.Charsets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * HttpUtil
 * http 工具类
 */
public final class HttpUtil {

    private final static Logger LOGGER= LoggerFactory.getLogger(HttpUtil.class);

    private final static String UTF_8 = "UTF-8";

    /**
     * get 请求，返回原数据
     * @param url
     * @return
     */
    public static String doGet(String url){
        return doGet(url,null);
    }

    /**
     * get 请求，返回原数据
     * @param url
     * @param headerMap
     * @return
     */
    public static String doGet(String url,Map<String,String> headerMap){
        StringBuffer data = null;
        try {
            //创建连接
            HttpURLConnection connection = getConnection(url,headerMap);
            connection.connect();
            data = readData(connection);
            connection.disconnect();
        } catch (IOException e) {
            LOGGER.error(e.getMessage(),e);
        }
        return data == null ? null : data.toString();
    }

    /**
     * Get 请求 返回map
     * @param url
     * @return
     */
    public static Map<String,Object> doGetMap(String url){
      return doGetMap(url,null);
    }

    /**
     * Get 请求 返回map
     * @param url
     * @return
     */
    public static Map<String,Object> doGetMap(String url,Map<String,String> headerMap){
        String data = doGet(url,headerMap);
        Map<String,Object> returnMap = new HashMap<String, Object>();
        return data !=null && data.length() > 0 ? JSONObject.parseObject(data,new TypeReference<Map<String,Object>>(){}) : returnMap;
    }

    /**
     * Get 请求 返回map
     * @param url
     * @return
     */
    public static JSONObject doGetJson(String url){
       return doGetJson(url,null);
    }

    /**
     * Get 请求 返回map
     * @param url
     * @return
     */
    public static JSONObject doGetJson(String url,Map<String,String> headerMap){
        String data = doGet(url,headerMap);
        return data !=null && data.length() > 0 ? JSONObject.parseObject(data) : null;
    }


    /**
     * Json 提交
     * @Title: doJsonPost
     * @Description: 提交json请求信息
     * @param url
     * @param jsonObj
     * @return
     */
    public static String doPost(String url, JSONObject jsonObj){
        return doPost(url,jsonObj,null);
    }

    /**
     * Json 提交
     * @Title: doJsonPost
     * @Description: 提交json请求信息
     * @param url
     * @param jsonObj
     * @return
     */
    public static String doPost(String url, JSONObject jsonObj,Map<String,String> headerMap){
        return doPost(url,jsonObj ==null ? null : jsonObj.toJSONString(),headerMap);
    }

    /**
     * Json 提交
     * @Title: doJsonPost
     * @Description: 提交json请求信息
     * @param url
     * @param jsonObj
     * @return
     */
    public static Map<String,Object> doPostMap(String url, JSONObject jsonObj){
       return doPostMap(url,jsonObj,null);
    }

    /**
     * Json 带头信息提交
     * @param url
     * @param jsonObj
     * @param headerMap
     * @return
     */
    public static JSONObject doPostJson(String url, JSONObject jsonObj,Map<String,String> headerMap){
        return doPostJson(url,jsonObj ==null ? null : jsonObj.toJSONString(),headerMap);
    }
    /**
     * Json 带头信息提交
     * @param url
     * @param jsonObj
     * @param headerMap
     * @return
     */
    public static Map<String,Object> doPostMap(String url, JSONObject jsonObj,Map<String,String> headerMap){
       return doPostMap(url,jsonObj ==null ? null : jsonObj.toJSONString(),headerMap);
    }

    /**
     * Json 带头信息提交
     * @param url
     * @param reqStr
     * @param headerMap
     * @return
     */
    public static JSONObject doPostJson(String url, String reqStr,Map<String,String> headerMap){
        String data = doPost(url,reqStr,headerMap);
        return data != null && data.length() > 0 ? JSONObject.parseObject(data) : null;
    }
    /**
     * Json 带头信息提交
     * @param url
     * @param reqStr
     * @param headerMap
     * @return
     */
    public static Map<String,Object> doPostMap(String url, String reqStr,Map<String,String> headerMap){
        String data = doPost(url,reqStr,headerMap);
        return data != null && data.length() > 0 ? JSONObject.parseObject(data,new TypeReference<Map<String,Object>>(){}) : null;
    }


    /**
     *
     * @Title: doStringPost
     * @Description: 提交json请求信息
     * @param url
     * @param reqStr
     * @param headerMap
     * @return
     */
    public static String doPost(String url,String reqStr,Map<String,String> headerMap) {
        StringBuffer sb = new StringBuffer("");
        try {
            //创建连接
            URL doUrl = new URL(url);
            HttpURLConnection connection = (HttpURLConnection) doUrl .openConnection();
            setHeader(connection,headerMap,HttpMethod.POST,ContentType.JSON);
            connection.connect();
            writeStrData(connection,reqStr);
            sb = readData(connection);
            connection.disconnect();
        } catch (IOException e) {
            LOGGER.error(e.getMessage(),e);
        }
        return sb.length() > 0 ? sb.toString() : null;
    }

    /**
     * 获取连接对象
     * @param url
     * @return
     * @throws IOException
     */
    static HttpURLConnection getConnection(String url) throws IOException{
        return getConnection(url,null,HttpMethod.GET,ContentType.URL_ENCODED);
    }

    /**
     * 获取连接对象
     * @param url
     * @param headerMap
     * @return
     * @throws IOException
     */
    static HttpURLConnection getConnection(String url,Map<String,String> headerMap) throws IOException{
        return getConnection(url,headerMap,ContentType.URL_ENCODED);
    }

    /**
     * 获取连接对象
     * @param url
     * @param headerMap
     * @param contentType
     * @return
     * @throws IOException
     */
    static HttpURLConnection getConnection(String url,Map<String,String> headerMap,ContentType contentType) throws IOException{
        return getConnection(url,headerMap,HttpMethod.GET,contentType);
    }

    /**
     * 获取连接对象
     * @param url
     * @param headerMap
     * @param method
     * @param contentType
     * @return
     * @throws IOException
     */
    static HttpURLConnection getConnection(String url,Map<String,String> headerMap,HttpMethod method,ContentType contentType) throws IOException{
        URL doUrl = new URL(url);
        HttpURLConnection connection = (HttpURLConnection) doUrl.openConnection();
        setHeader(connection,headerMap,method,contentType);
        return connection;
    }


    /**
     * 设置请求头信息
     * @param connection
     * @param headerMap
     */
    static void setHeader(HttpURLConnection connection ,Map<String,String> headerMap,HttpMethod method,ContentType contentType){
        if(headerMap != null && headerMap.size() > 0 ){
            Set<Map.Entry<String,String>> headers = headerMap.entrySet();
            for (Map.Entry<String,String> entry : headers ) {
                connection.setRequestProperty(entry.getKey(),entry.getValue());
            }
        }
        setDefaultHeader(connection,method,contentType);
    }

    /**
     * 设置默认头信息
     * @param connection
     * @param method
     * @param contentType
     */
    static void setDefaultHeader(HttpURLConnection connection,HttpMethod method,ContentType contentType){
        try{
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setUseCaches(false);
            connection.setInstanceFollowRedirects(true);
            connection.setRequestProperty("Content-Type",contentType.getValue());
            connection.setRequestMethod(method.name());
        } catch (Exception ex){}
    }

    /**
     * 写入String
     * @param connection
     * @param json
     * @throws IOException
     */
    static void writeStrData(HttpURLConnection connection,String json) throws IOException {
        DataOutputStream out = new DataOutputStream(connection.getOutputStream());
        out.write(json.getBytes(Charsets.UTF_8));
        out.flush();
        out.close();
    }

    /**
     * 读取请求返回数据
     * @param connection
     * @return
     * @throws IOException
     */
    static StringBuffer readData(HttpURLConnection connection) throws IOException{
        StringBuffer sb = new StringBuffer("");
        BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8));
        String lines;
        while ((lines = reader.readLine()) != null) {
            lines = new String(lines.getBytes(UTF_8), UTF_8);
            sb.append(lines);
        }
        LOGGER.info(sb.toString());
        reader.close();
        return sb;
    }

    /**
     * 请求方式
     */
    enum HttpMethod{
        GET,
        POST,
        ;
    }

    /**
     * 请求类型
     */
    enum ContentType{
        JSON("application/json"),

        URL_ENCODED("application/x-www-form-urlencoded"),
        ;
        private String value;
        ContentType(String value){
            this.value = value;
        }

        public String getValue(){
            return this.value;
        }

    }


}
